Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SimpleBarrier and @barrier #97

Merged
merged 11 commits into from
Mar 22, 2024
Merged

SimpleBarrier and @barrier #97

merged 11 commits into from
Mar 22, 2024

Conversation

carstenbauer
Copy link
Member

@carstenbauer carstenbauer commented Mar 21, 2024

Preliminary attempt at #74.

Adds a SimpleBarrier to OhMyThreads.Tools and introduces OhMyThreads.Experimental.@barrier (to be used within @tasks). All of this is internal/experimental and not officially made public API. The primary reason is that one can rather easily hit deadlocks. Let me quote the docstring of @barrier:

help?> OhMyThreads.Experimental.@barrier
  @barrier


  This can be used inside a @tasks for ... end to synchronize n parallel tasks.
  Specifically, a task can only pass the @barrier if n-1 other tasks have reached it
  as well. The value of n is determined from @set ntasks=..., which is required if one
  wants to use @barrier.

  Because this feature is experimental, it is required to load @barrier explicitly,
  e.g. via using OhMyThreads.Experimental: @barrier.

  WARNING: It is the responsibility of the user to ensure that the right number of
  tasks actually reach the barrier. Otherwise, a deadlock can occur. In partictular,
  if the number of iterations is not a multiple of n, the last few iterations
  (remainder) will be run by less than n tasks which will never be able to pass a
  @barrier.

  Example
  =======

  using OhMyThreads: @tasks
  
  # works
  @tasks for i in 1:20
      @set ntasks = 20
  
      sleep(i * 0.2)
      println(i, ": before")
      @barrier
      println(i, ": after")
  end
  
  # wrong - deadlock!
  @tasks for i in 1:22 # ntasks % niterations != 0
      @set ntasks = 20
  
      println(i, ": before")
      @barrier
      println(i, ": after")
  end

@carstenbauer
Copy link
Member Author

To make the experimental status even more explicit, I've made it so that one has to explicitly load OhMyThreads.Experimental.@barrier for it to work within @tasks.

julia> using OhMyThreads

julia> @tasks for i in 1:3
           @set ntasks = 3
       
           sleep(i * 0.2)
           println(i, ": before")
           @barrier
           println(i, ": after")
       end
ERROR: UndefVarError: `@barrier` not defined

julia> using OhMyThreads.Experimental: @barrier

julia> @tasks for i in 1:3
           @set ntasks = 3
       
           sleep(i * 0.2)
           println(i, ": before")
           @barrier
           println(i, ": after")
       end
1: before
2: before
3: before
3: after
1: after
2: after

(If there is a different @barrier around, we throw an error.)

@carstenbauer
Copy link
Member Author

@MasonProtter I plan to merge this later today unless you have objections (to @barrier specifically or the whole OhMyThreads.Experimental thing).

@MasonProtter
Copy link
Member

Yeah makes sense to me!

@carstenbauer carstenbauer merged commit af51162 into master Mar 22, 2024
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants